/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package main;

import java.util.ArrayList;
import java.util.Random;

/**
 *
 * @author sbavdhorst
 */
public class DenseSetGenerator {
    private static Random generator = new Random();
    
    //generate one random set of this size with 1 quartet for every 4 taxa
    //if number = 1 then 1 quartet for every 4 taxa
    //if number = 2 then 2 quartets for every 4 taxa
    //else 1 or 2 quartets for every 4 taxa
    public static ArrayList<Quartet> randomSet(int size, int number){
        char[] alphabet = generateAlphabet(size);
        
        ArrayList<Quartet> set = new ArrayList<>();
        for(int i = 0; i<alphabet.length-3; i++){   //abcde -> abcd - abce - abde - acde - bcde
            for(int j = i+1; j< alphabet.length-2;j++){
                for(int k = j+1; k<alphabet.length-1; k++){
                    for(int l = k+1; l<alphabet.length; l++){
                        if(number == 1)
                            set.add(select1Quartet(new char[]{alphabet[i],alphabet[j],alphabet[k],alphabet[l]}));
                        else if(number == 2){
                            Quartet[] q = select2Quartets(new char[]{alphabet[i],alphabet[j],alphabet[k],alphabet[l]});
                            set.add(q[0]);
                            set.add(q[1]);
                        } else {
                            if(generator.nextBoolean())
                                set.add(select1Quartet(new char[]{alphabet[i],alphabet[j],alphabet[k],alphabet[l]}));
                            else{
                                Quartet[] q = select2Quartets(new char[]{alphabet[i],alphabet[j],alphabet[k],alphabet[l]});
                                set.add(q[0]);
                                set.add(q[1]);
                            }
                        }
                    }
                }
            }
        }
        return set;
    }
    
    //select 1 quartet made out of the 4 taxa given
    private static Quartet select1Quartet(char[] alphabet){
        int r = generator.nextInt(3);
        if(r<=0)        //ab|cd
            return new Quartet(new char[]{alphabet[0], alphabet[1]}, new char[]{alphabet[2], alphabet[3]});
        else if(r <=1)  //ac|bd
            return new Quartet(new char[]{alphabet[0], alphabet[2]}, new char[]{alphabet[1], alphabet[3]});
        else            //ad|bc
            return new Quartet(new char[]{alphabet[0], alphabet[3]}, new char[]{alphabet[1], alphabet[2]});
    }
    
    //select 2 different quartets made out of the 4 taxa given
    private static Quartet[] select2Quartets(char[] alphabet){
        int r = generator.nextInt(3);
        if(r<=0){           //ab|cd & ac|bd
            return new Quartet[]{new Quartet(new char[]{alphabet[0], alphabet[1]}, new char[]{alphabet[2], alphabet[3]}),
                                 new Quartet(new char[]{alphabet[0], alphabet[2]}, new char[]{alphabet[1], alphabet[3]})};
        } else if(r <=1){   //ab|cd & ad|bc
            return new Quartet[]{new Quartet(new char[]{alphabet[0], alphabet[1]}, new char[]{alphabet[2], alphabet[3]}),
                                 new Quartet(new char[]{alphabet[0], alphabet[3]}, new char[]{alphabet[1], alphabet[2]})};
        } else{               //ac|bd & ad|bc
            return new Quartet[]{new Quartet(new char[]{alphabet[0], alphabet[2]}, new char[]{alphabet[1], alphabet[3]}),
                                 new Quartet(new char[]{alphabet[0], alphabet[3]}, new char[]{alphabet[1], alphabet[2]})};
        }
    }
    
    //generate all sets of this size
    public static ArrayList<ArrayList<Quartet>> allSets(int size){
        char[] alphabet = generateAlphabet(size);
        ArrayList<Quartet[]> smallSets = new ArrayList<>();
        
        ArrayList<Quartet> firstSet = new ArrayList<>();
        for(int i = 0; i<alphabet.length-3; i++){   //abcde -> abcd - abce - abde - acde - bcde
            for(int j = i+1; j< alphabet.length-2;j++){
                for(int k = j+1; k<alphabet.length-1; k++){
                    for(int l = k+1; l<alphabet.length; l++){
                        firstSet.add(new Quartet(new char[]{alphabet[i], alphabet[j]}, new char[]{alphabet[k], alphabet[l]}));
                    }
                }
            }
        }
        
        ArrayList<Quartet> secondSet = new ArrayList<>();
        ArrayList<Quartet> thirdSet = new ArrayList<>();
        for(Quartet q: firstSet){
            secondSet.add(new Quartet(new char[]{q.getPair1()[0], q.getPair2()[0]}, new char[]{q.getPair1()[1], q.getPair2()[1]}));
            thirdSet.add(new Quartet(new char[]{q.getPair1()[0], q.getPair2()[1]}, new char[]{q.getPair1()[1], q.getPair2()[0]}));
        }
        
        for(int i = 0; i<firstSet.size(); i++){
            smallSets.add(new Quartet[]{firstSet.get(i), secondSet.get(i), thirdSet.get(i)});
        }
        
        return allCombinations(smallSets);         
    }
    
    // used for generating all the sets
    private static ArrayList<ArrayList<Quartet>> allCombinations(ArrayList<Quartet[]> smallSets){
        ArrayList<ArrayList<Quartet>> allSets = new ArrayList<>();
        if(smallSets.size() == 1){
            ArrayList<Quartet> first = new ArrayList<>();
            first.add(smallSets.get(0)[0]);
            allSets.add(first);
            ArrayList<Quartet> second = new ArrayList<>();
            second.add(smallSets.get(0)[1]);
            allSets.add(second);
            ArrayList<Quartet> third = new ArrayList<>();
            third.add(smallSets.get(0)[2]);
            allSets.add(third);
        }else{
            Quartet[] removed = smallSets.get(0);
            smallSets.remove(0);
            ArrayList<ArrayList<Quartet>> all = allCombinations(smallSets);
            for(int i = 0; i<all.size(); i++){
                ArrayList<Quartet> list = all.get(i);
                list.add(0, removed[0]);
                allSets.add((ArrayList<Quartet>) list.clone());
                list.remove(0);
                list.add(0, removed[1]);
                allSets.add((ArrayList<Quartet>) list.clone());
                list.remove(0);
                list.add(0, removed[2]);
                allSets.add((ArrayList<Quartet>) list.clone());
            }
        }
        
        return allSets;
    }
    
    public static char[] generateAlphabet(int size){
        char[] alphabet = new char[size];
        for(int i = 0; i< alphabet.length; i++){
            alphabet[i] = (char) (i+97);
        }
        return alphabet;
    }
    
    //if number = 1 then 1 quartet for every 4 taxa
    //if number = 2 then 2 quartets for every 4 taxa
    //else 1 or 2 quartets for every 4 taxa
    public static ArrayList<Quartet> setFromCircle(int size, Circle c, int number){
        ArrayList<ArrayList<Quartet>> allQuartets = c.getAllQuartets();
        ArrayList<Quartet> set = new ArrayList<>();
        
        for(ArrayList<Quartet> q: allQuartets){
            if(number == 1){
                if(generator.nextBoolean())
                    set.add(q.get(0));
                else
                    set.add(q.get(1));
            } else if (number == 2){
                set.add(q.get(0));
                set.add(q.get(1));
            } else{
                boolean b = generator.nextBoolean();
                if(b)
                    set.add(q.get(0));
                if(!b || generator.nextBoolean())
                    set.add(q.get(1));
            }
        }
        return set;
    }
    
    public static void main(String[] args){
//        ArrayList<Quartet> set = randomSet(5,2);
//        for(Quartet q: set){
//            System.out.println(q);
//        } 
        
        boolean b = true;
        int i = 0;
        for(ArrayList<Quartet> list: allSets(6)){
            i++;
            System.out.println("Uiteindelijke Lijst " + i);
            for(Quartet q: list){
                System.out.println(q);
            }
            if(Solver.bruteForce(list, 6).isEmpty())
                b = false;
        }
        System.out.println(b);
    }
}
